<?php
namespace app\api\logic;

use app\api\consDir\ErrorConst;
use app\api\services\MemberService;
use app\api\services\OrderService;
use app\api\services\ShopService;
use app\api\services\SupplyService;
use app\common\libs\Singleton;
use app\common\models\Order\Order;
use app\common\utils\CommonUtil;
use app\common\utils\RedLock;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use \app\common\models\ExchangeGoods;
use \app\common\models\ExchangeOrder;
use \app\common\models\ExchangeOrderAddress;
use \app\common\models\ExchangeOrderGoods;
use \app\common\models\ExchangeOrderSub;

/**
 * 订单模块
 * Class ExchangeOrderLogic
 * @package app\api\logic
 */
class ExchangeOrderLogic extends BaseLogic
{
    use Singleton;

    /**
     * @param $orderNo
     * @param $goodsId
     * @return array|mixed|void
     */
    public function orderExpress($orderNo, $goodsId)
    {
        $where = [
            'order_no' => $orderNo,
            'deleted'  => 0,
            'goods_id' => $goodsId,
        ];
        $field = [
            'express_name',
            'express_no',
            'express_code',
            'state',
            'express_info',
            'user_id',
        ];
        $express = \think\facade\Db::table('exchange_order_express')
            ->field($field)
            ->where($where)
            ->find();
        if (empty($express)) {
            $where = [
                'order_no' => $orderNo,
                'deleted'  => 0,
            ];
            $express = \think\facade\Db::table('exchange_order_express')
                ->field($field)
                ->where($where)
                ->find();
        }
        // var_dump($this->userinfo->id);exit;
        if (empty($express)) {
            return [];
        }
        if ($express['user_id'] != $this->userinfo->id) {
            CommonUtil::throwException(
                ErrorConst::PARAM_ERROR,
                ErrorConst::PARAM_ERROR_MSG
            );
        }
        // 快递单当前状态，默认为0在途，1揽收，2疑难，3签收，4退签，5派件，8清关，14拒签等10个基础物流状态，如需要返回高级物流状态，请参考 resultv2 传值
        $state = $express['state'];
        if ($state == 3 || $state == 4 || $state == 14) {
            $expressList = json_decode($express['express_info'], true);
            return [
                'expressNo'   => $express['express_no'],
                'expressName' => $express['express_name'] ?? '',
                'expressCode' => $express['express_code'] ?? '',
                'expressList' => $expressList,
            ];
        }
        $data = \app\api\services\ExpressService::getInstance()->query([
            'expressCode' => $express['express_code'],
            'expressNo'   => $express['express_no'],
        ]);

        if(isset($data['result']) && !$data['result']){
            $error = $data['message'] ?? '快递查询服务故障';
            return [];
        }

        /*
        if (empty($data['state'])) {
            $this->error = $data['message'] ?? '快递查询服务故障';
            return [];
        }*/
        $expressList = $data['data'] ?? [];
        \think\facade\Db::table('exchange_order_express')
            ->where($where)
            ->update([
                'update_at'    => date('Y-m-d H:i:s'),
                'state'        => $data['state'],
                'express_code' => $data['com'] ?? '',
                'express_info' => json_encode($expressList, 320),
            ]);

        return [
            'expressNo'   => $express['express_no'],
            'expressName' => $express['express_name'] ?? '',
            'expressCode' => $data['com'] ?? '',
            'expressList' => $expressList,
        ];
    }

    private function getOrderInfo($orderNo, $uid): array
    {
        $where = [
            ['order_no', '=', $orderNo],
            ['user_id', '=', $uid],
        ];
        $field = [
            'id',
            'status',
            'pay_price',
            'pay_amount',
            'order_no',
            'order_type',
            'status',
            'sale',
            'postage',
            'sell_price',
            'is_comment',
            'refund_at',
            'trade_no',
            'expire_at',
            'pay_at',
            'deliver_at',
            'create_at',
            'coupon_id ',
            'user_note',
            'deleted',
            'exchange_type',
            'pay_coin',
        ];
        $order = ExchangeOrder::getInstance()
            ->where($where)
            ->field($field)
            ->find();
        return empty($order) ? [] : $order->toArray();
    }
    private function getOrderAddress($orderNo): array
    {
        $where = [
            'order_no' => $orderNo,
        ];
        $field = [
            'province',
            'city',
            'country',
            'street',
            'comm',
            'address',
            'phone',
            'real_name',
        ];
        $address = \app\common\models\ExchangeOrderAddress::getInstance()
            ->field($field)
            ->where($where)
            ->find();
        // var_dump($address);exit;
        return empty($address) ? [] : $address->toArray();
    }

    private function getOrderSubInfo($orderNo): array
    {
        $where = [
            'order_no' => $orderNo,
        ];
        $field = [
            'shop_id',
            'shop_name',
            'quantity',
            'pay_coin',
            'pay_price',
            'postage',
            'sale',
            'order_no',
            'sub_order_no',
        ];
        $subOrders = ExchangeOrderSub::getInstance()
            ->where($where)
            ->field($field)
            ->select();
        $subOrders = empty($subOrders) ? [] : $subOrders->toArray();
        if (empty($subOrders)) {
            return [];
        }
        $field = [
            'goods_id',
            'goods_img',
            'goods_title',
            'id',
            'sku_title',
            'is_freight_insurance',
            'is_seven',
            'sell_price',
            'quantity',
            'exchange_coin pay_coin',
            'pay_price',
            'status',
        ];
        foreach ($subOrders as &$v) {
            $where = [
                ['order_no', '=', $v['orderNo']],
                ['shop_id', '=', $v['shopId']],
            ];
            $v['goodsInfo'] = ExchangeOrderGoods::getInstance()
                ->where($where)
                ->field($field)
                ->select()
                ->toArray();

            //读取店铺信息
            $v['shop_logo']         = "";
            $v['kf_phone']          = "";
            $v['shop_business_img'] = "";
            if ($v['shopId'] != 0) {
                $shopWhere = ['id' => (int) $v['shopId']];
                $shopInfos = \app\common\models\Shop\Shop::getInstance()
                    ->where($shopWhere)
                    ->find();

                $v['shop_logo']         = $shopInfos['shop_logo'];
                $v['shop_business_img'] = $shopInfos['shop_business_img'];
                $v['kf_phone']          = $shopInfos['kf_phone'];
            }
        }

        return $subOrders;
    }

    /**
     * @param $orderNo
     * @return array
     */
    public function orderDetail($orderNo): array
    {
        // $this->userinfo->id = 1000031;
        $order = $this->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($order)) {
            CommonUtil::throwException(
                ErrorConst::PARAM_ERROR,
                ErrorConst::PARAM_ERROR_MSG);
        }
        $expireTime            = strtotime($order['expireAt']) - time();
        $order['deliveryType'] = '普通快递';
        $order['expireTime']   = $expireTime > 0 ? $expireTime : 0;

        $orderAddress = $this->getOrderAddress($orderNo);
        // var_dump($orderAddress);exit;

        $orderShop = $this->getOrderSubInfo($orderNo);

        // $supplyGoods = OrderGoods::getInstance()->where('order_no', $order['orderNo'])->select();

        // exchangeCoin_4_to_2
        $order['payCoin'] = number_format($order['payCoin'], 2, '.', '');
        if ( ! empty($orderShop)) {
            foreach ($orderShop as &$sub) {
                // exchangeCoin_4_to_2
                $sub['payCoin'] = number_format($sub['payCoin'], 2, '.', '');
                if ( ! empty($sub['goodsInfo'])) {
                    foreach ($sub['goodsInfo'] as &$val) {
                        // exchangeCoin_4_to_2
                        $val['payCoin'] = number_format($val['payCoin'], 2, '.', '');
                    }
                }
            }
        }

        $serviceInfo = [
            'phone'  => 18938511389,
            'wechat' => 'rxx',
        ];
        return [
            'orderInfo'    => $order, // 总订单信息
            'orderAddress' => $orderAddress,
            'orderShop'    => $orderShop, // 子订单信息
            'serviceInfo'  => $serviceInfo,
            // 'supplyGoods'  => $supplyGoods,
        ];
    }

    public function delOrder($orderNo): bool
    {
        $orderInfo = $this->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($orderInfo)) {
            CommonUtil::throwException(
                ErrorConst::PARAM_ERROR,
                ErrorConst::PARAM_ERROR_MSG
            );
        }
        // 0待支付 1待发货 2待收货 3已收货 4已完成 5退款中 6退款成功 7取消 8超时取消 9待退货
        if ( ! in_array($orderInfo['status'], [0, 4, 6, 7, 8])) {
            CommonUtil::throwException(
                ErrorConst::ORDER_STATUS_ERROR,
                ErrorConst::ORDER_STATUS_ERROR_MSG
            );
        }
        // var_dump($orderInfo['deleted']);exit;
        if ($orderInfo['deleted'] == 1) {
            return true;
        }
        ExchangeOrder::getInstance()->startTrans();
        try {
            //修改退款状态
            $order = ExchangeOrder::getInstance()
                ->where('id', $orderInfo['id'])
                ->update(['deleted' => 1]);
            if ( ! $order) {
                return false;
            }
            // orderType 1线下直付单 2线上单 3线下单 4供应链
            if ($orderInfo['orderType'] != 4) {
                $orderShop = ExchangeOrderSub::getInstance()
                    ->where('order_no', $orderInfo['orderNo'])
                    ->update(['deleted' => 1]);
                if ( ! $orderShop) {
                    ExchangeOrder::getInstance()->rollback();
                    return false;
                }
            }

            $orderGoods = ExchangeOrderAddress::getInstance()
                ->where('order_no', $orderInfo['orderNo'])
                ->update(['deleted' => 1]);

            $orderGoods = ExchangeOrderGoods::getInstance()
                ->where('order_no', $orderInfo['orderNo'])
                ->update(['deleted' => 1]);
            if ( ! $orderGoods) {
                ExchangeOrder::getInstance()->rollback();
                return false;
            }

            \think\facade\Db::table('exchange_order_express')
                ->where('order_no', $orderInfo['orderNo'])
                ->update(['deleted' => 1]);
            ExchangeOrder::getInstance()->commit();
            return true;
        } catch (\Exception $e) {
            $msg = json_encode(['message' => $e->getMessage(), 'trace' => $e->getTrace()], 320);
            \think\facade\Log::error('[ExchangeOrder/delOrder] 出错' . $msg);
        }
        return false;
    }

    /**
     * 取消并退款
     * @param $orderNo
     * @return bool
     */
    public function cancelOrder($orderNo): bool
    {
        $order = $this->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($order)) {
            CommonUtil::throwException(
                ErrorConst::PARAM_ERROR,
                ErrorConst::PARAM_ERROR_MSG
            );
        }

        // 0待支付 1待发货 2待收货 3已收货 4已完成 5退款中 6退款成功 7取消 8超时取消 9待退货
        if ($order['status'] == 0) { // 未支付取消
            $update = [
                'status'    => 7,
                'refund_at' => date('Y-m-d H:i:s'),
            ];
            $where = [
                ['order_no', '=', $orderNo],
                ['status', '=', 0],
            ];
            \think\facade\Db::table('exchange_order')
                ->where($where)->update($update);
            \think\facade\Db::table('exchange_order_sub')
                ->where($where)->update($update);
            \think\facade\Db::table('exchange_order_goods')
                ->where($where)->update($update);
            return true;
        } elseif ($order['status'] == 7) { // 待发货取消
            return true;
        } elseif ($order['status'] != 1) { // 待发货取消
            CommonUtil::throwException(
                ErrorConst::NO_ORDER_ERROR,
                ErrorConst::NO_ORDER_ERROR_MSG
            );
        }

        //30分钟
        $date = date('Y-m-d H:i:s', strtotime('-30 minutes'));
        if ($order['payAt'] < $date) {
            CommonUtil::throwException(
                ErrorConst::ORDER_TIME_ERROR,
                ErrorConst::ORDER_TIME_ERROR_MSG
            );
        }
        //退款逻辑
        $refund = $this->orderRefund($order);
        if ( ! $refund) {
            CommonUtil::throwException(
                ErrorConst::ORDER_REFUND_ERROR,
                ErrorConst::ORDER_REFUND_ERROR_MSG
            );
        }
        return true;
    }

    /**
     * 退款相关积分
     * @param $orderInfo
     * @return bool
     */
    private function orderRefund($orderInfo)
    {
        ExchangeOrder::getInstance()->startTrans();
        try {
            //修改退款状态
            $order = ExchangeOrder::getInstance()
                ->where('id', $orderInfo['id'])
                ->update(['status' => 7, 'refund_at' => date('Y-m-d H:i:s')]);

            if ( ! $order) {
                return false;
            }

            $orderShop = ExchangeOrderSub::getInstance()
                ->where('order_no', $orderInfo['orderNo'])
                ->update(['status' => 7, 'refund_at' => date('Y-m-d H:i:s')]);
            if ( ! $orderShop) {
                ExchangeOrder::getInstance()->rollback();
                return false;
            }

            $orderGoods = ExchangeOrderGoods::getInstance()
                ->where('order_no', $orderInfo['orderNo'])
                ->update(['status' => 7, 'refund_at' => date('Y-m-d H:i:s')]);
            if ( ! $orderGoods) {
                ExchangeOrder::getInstance()->rollback();
                return false;
            }
            if ($orderInfo['payAmount'] > 0) {
                $msg     = '订单取消，退回余额：' . $orderInfo['payAmount'];
                $finance = MemberService::getInstance()
                    ->addFinanceLog($orderInfo['userId'], 'order_cancel', $orderInfo['payAmount'], 1, $msg);
                if ( ! $finance) {
                    ExchangeOrder::getInstance()->rollback();
                    return false;
                }
            }
            if ($orderInfo['payCoin'] > 0) {
                $coin    = $orderInfo['payCoin'];
                $orderNo = $orderInfo['orderNo'];
                $finance = MemberService::getInstance()->finance($this->userinfo->id);
                // 兑换类型 1 琅狼积分兑换 2 数字资产兑换 4 贡献值兑换
                if ($orderInfo['exchangeType'] == 1) {
                    $msg = '抵扣券兑换商品，取消订单' . $orderNo;
                    $this->changeCoin(
                        'exchange_refund',
                        'member_langlang_score_log',
                        'langlang_score',
                        'inc',
                        $coin,
                        $finance['langlangScore'],
                        $finance['userId'],
                        $msg,
                        $orderNo,
                    );
                } elseif ($orderInfo['exchangeType'] == 2) {
                    $msg = '数字资产兑换商品，取消订单' . $orderNo;
                    $this->changeCoin(
                        'exchange_refund',
                        'member_digital_money_log',
                        'digital_money',
                        'inc',
                        $coin,
                        $finance['digitalMoney'],
                        $finance['userId'],
                        $msg,
                        $orderNo,
                    );
                } elseif ($orderInfo['exchangeType'] == 4) {
                    $msg = '贡献值兑换商品，取消订单' . $orderNo;
                    $this->changeCoin(
                        'exchange_refund',
                        'member_gxz_log',
                        'gxz',
                        'inc',
                        $coin,
                        $finance['gxz'],
                        $finance['userId'],
                        $msg,
                        $orderNo,
                    );
                }
            }

            ExchangeOrder::getInstance()->commit();
            return true;

        } catch (\Exception $e) {
            ExchangeOrder::getInstance()->rollback();
            $msg = json_encode(['message' => $e->getMessage(), 'trace' => $e->getTrace()], 320);
            \think\facade\Log::error('[ExchangeOrder/orderRefund] 出错' . $msg);
            return false;

        }
        return false;
    }

    /**
     * @param $type
     * @param $orderType
     * @param $page
     * @param $pageSize
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function orderList($type, $orderType, $page, $pageSize): array
    {
        $uId = $this->userinfo->id;
        //1全部 2待付款 3待发货 4待收货 5待评价 6售后
        switch ($type) {
            case 1:
                $where = [
                    ['user_id', '=', $uId],
                    ['deleted', '=', 0],
                ];
                break;
            case 2:
                $where = [
                    ['user_id', '=', $uId],
                    ['status', '=', 0],
                    ['deleted', '=', 0],
                ];
                break;
            case 3:
                $where = [
                    ['user_id', '=', $uId],
                    ['status', '=', 1],
                    ['deleted', '=', 0],
                ];
                break;
            case 4:
                $where = [
                    ['user_id', '=', $uId],
                    ['status', '=', 2],
                    ['deleted', '=', 0],
                ];
                break;
            case 5:
                $where = [
                    ['user_id', '=', $uId],
                    ['status', '=', 3],
                    ['is_comment', '=', 0],
                    ['deleted', '=', 0],
                ];
                break;
            default:
                $where = [
                    ['user_id', '=', $uId],
                    ['status', 'in', [5, 6]],
                    ['deleted', '=', 0],
                ];
        }
        if ($orderType == 2) {
            $where[] = ['order_type', 'in', [2, 4]];
        } else {
            $where[] = ['order_type', 'in', [1, 3]];
        }
        // `exchange_type` int(11) DEFAULT '0' COMMENT '1 琅狼积分兑换  2 数字资产兑换  4 贡献值兑换',
        // `order_type`tinyint(4)default'1'COMMENT'1线下直付单 2线上单 3线下单 4供应链',

        $field = [
            'id',
            'status',
            'order_no',
            'user_id',
            'sell_price',
            'order_type',
            'postage',
            'sale',
            'pay_at',
            'pay_price',
            'pay_amount',
            'pay_coin',
            'create_at',
            'expire_at',
            'is_comment',
            'exchange_type',
        ];
        $list = ExchangeOrder::getInstance()
            ->where($where)
            ->limit(($page - 1) * $pageSize, $pageSize)
            ->field($field)
            ->order('id desc')
            ->select();
        if (empty($list)) {
            return [];
        }
        $goodsField = [
            'is_freight_insurance',
            'is_seven',
            'status',
            'quantity',
            'exchange_coin pay_coin',
            'pay_price',
            'sell_price',
            'goods_id',
            'goods_title',
            'sku_title',
            'goods_img',
        ];
        $list = $list->toArray();
        foreach ($list as &$val) {
            // exchangeCoin_4_to_2
            $val['payCoin'] = number_format($val['payCoin'], 2, '.', '');

            $where = [
                ['order_no', '=', $val['orderNo']],
            ];

            $orderShop = ExchangeOrderSub::getInstance()->where($where)->find();

            $val['shopInfo'] = ShopService::getInstance()->getShopInfoById($orderShop['shopId'], 'id,shop_logo,shop_name,kf_phone');

            $orderInfo = ExchangeOrderGoods::getInstance()
                ->where($where)
                ->field($goodsField)
                ->select()->toArray();
            if ( ! empty($orderInfo)) {
                foreach ($orderInfo as $key => &$val2) {
                    // exchangeCoin_4_to_2
                    $val2['payCoin'] = number_format($val2['payCoin'], 2, '.', '');
                }
            }
            $val['createAt']   = date('Y-m-d H:i', strtotime($val['createAt']));
            $expireTime        = strtotime($val['expireAt']) - time();
            $val['expireTime'] = $expireTime > 0 ? $expireTime : 0;
            $val['goodsInfo']  = (array) $orderInfo;
        }
        return ['rows' => $list];
    }

    /**
     * 预计送到时间
     * @param  [type] $sendCity  [description]
     * @param  [type] $addressId [description]
     * @return [type]            [description]
     */
    public function estimatedDelivery($sendCity, $addressId, $startDate = null, $days = 3)
    {
        $city = '';
        if (is_numeric($sendCity)) {
            $sendCity = \think\facade\Db::table('member_shop')
                ->where('id', $addressId)
                ->value('city');
        }
        if (empty($startDate)) {
            $startDate = new \DateTime();
        }
        $startDate->modify("+{$days} day");
        $tips = '预计' . $startDate->format('n月j日') . '后送达';
        if (is_numeric($addressId)) {
            // var_dump($sendCity);exit;
            $city = \app\common\models\Member\Address::where('id', $addressId)
                ->value('city');
        } else if (is_string($addressId)) {
            $city = $addressId;
        }
        // 同城3天，不同城5天送达
        if ($city != $sendCity) {
            $startDate->modify("+2 day");
            $tips = '预计' . $startDate->format('n月j日') . '后送达';
        }
        return $tips;
    }

    /**
     * 获取商品信息
     * @param  int $source  商品来源：1 日兮香商品 2 怡亚通商品
     * @param  int $exchange_type 1 琅狼积分兑换 2 数字资产兑换 4 贡献值兑换
     * @param  [type] $goodsItems   [{"goodsId":1,"skuId":2, "quantity":1, "remark":""}, ...]
     * @return [type]                [description]
     */
    private function getOrderGoodsInfo($source, $exchange_type, $goodsItems)
    {
        $goodsField = [
            'g.id',
            'g.id as goods_id',
            'g.shop_id',
            'g.goods_title',
            'g.market_price',
            'g.goods_img',
            'g.goods_type',
            'g.goods_sales',
            // 'g.goods_inventory',
            'g.content',
            'g.is_sku',
            'g.goods_inside_img',
            'g.is_postage',
            'g.sp_id',
            'g.gxz_rate',
            'g.goods_tag',
            'g.goods_service',

            'eg.exchange_type',
            'eg.exchange_coin as exchange_coin',
            'eg.exchange_inventory as goods_inventory',
            'eg.exchange_price sell_price',
            'eg.exchange_count exchange_count',
        ];
        $skuField = [
            'id',
            'goods_sku_id',
            'exchange_type',
            'exchange_coin',
            'exchange_price sell_price', // 售价
            'exchange_inventory goods_inventory', // 兑换库存
            'cost_price', // 成本价
            'sku_img',
            'sku_title',
            'spu_id',
            'sku_id',
        ];

        $goodsField2 = [
            'g.id',
            'g.id as goods_id',
            '0 shop_id',
            'g.name goods_title',
            'g.market_price',
            'g.cover_img goods_img',
            '2 goods_type',
            'g.goods_sales',
            // 'g.goods_inventory',
            'g.description content',
            '1 is_sku',
            'g.detail_img_list goods_inside_img',
            'g.free_express is_postage',
            // 'g.sp_id',
            'g.gxz_rate',
            'g.goods_tag',
            'g.goods_service',

            'eg.exchange_type',
            'eg.exchange_coin as exchange_coin',
            'eg.exchange_inventory as goods_inventory',
            'eg.exchange_price sell_price',
            'eg.exchange_count exchange_count',
        ];
        $info = []; // [{"shopInfo":{}, "goodsInfo":[{},]}, ...]
        foreach ($goodsItems as $v) {
            if (empty($v['quantity']) || $v['quantity'] < 1 || empty($v['goodsId'])) {
                CommonUtil::throwException(
                    ErrorConst::PARAM_ERROR,
                    'goodsInfo 格式有误');
            }
            // use index idx_GoodsId_Del_Status
            // $goodsInfo = \app\data\model\Db::table('exchange_goods')
            if ($source == 1) {
                $goodsInfo = \app\common\models\ExchangeGoods::getInstance()
                    ->alias('eg')
                    ->join('goods g', 'eg.goods_id= g.id')
                    ->field($goodsField)
                    ->where('eg.goods_id', $v['goodsId'])
                    ->where('eg.deleted', 0)
                    ->where('eg.exchange_type', $exchange_type)
                // status 0审核中 1上架 2下架 3拒绝
                    ->where('g.status', 1)
                    ->find();
            } elseif ($source == 2) {
                $goodsInfo = \app\common\models\ExchangeGoods::getInstance()
                    ->alias('eg')
                    ->join('supply_goods g', 'eg.goods_id= g.id')
                    ->field($goodsField2)
                    ->where('eg.goods_id', $v['goodsId'])
                    ->where('eg.deleted', 0)
                    ->where('eg.exchange_type', $exchange_type)
                // status 商品状态：0、已上架1、已下架
                    ->where('g.status', 0)
                    ->find();
                // echo \app\common\models\ExchangeGoods::getlastsql();
            }

            // var_dump($goodsInfo);exit;
            if (empty($goodsInfo)) {
                $updateEGWhere = [
                    'goods_id'      => $v['goodsId'],
                    'exchange_type' => $exchange_type,
                ];
                \app\common\models\ExchangeGoods::getInstance()->where($updateEGWhere)
                // 1 在线 2下线
                    ->update([
                        'status'    => 2,
                        'update_at' => date('Y-m-d H:i:s'),
                    ]);
                CommonUtil::throwException(
                    ErrorConst::NO_GOODS_ERROR,
                    ErrorConst::NO_GOODS_ERROR_MSG);
            }
            // var_dump($goodsInfo['goodsInventory']);exit;
            if ($goodsInfo['goodsInventory'] < 1 || ($goodsInfo['goodsInventory'] - $v['quantity']) < 0) {
                CommonUtil::throwException(
                    ErrorConst::NO_GOODS_ERROR,
                    '商品库存不足');
                continue;
            }
            $isSku = $goodsInfo['isSku'] ?? 0;
            if ($isSku == 1) {
                // $sku = GoodsService::getInstance()->skuInfo($v['goodsId'], $v['skuId'], 'id,sell_price,goods_inventory,cost_price,sku_img,sku_title');
                $sku = \think\facade\Db::table('exchange_goods_sku')
                    ->field($skuField)
                    ->where([
                        'goods_id'      => $v['goodsId'],
                        'deleted'       => 0,
                        'exchange_type' => $exchange_type,
                        'goods_sku_id'  => $v['skuId'],
                    ])
                    ->find();
                // var_dump($sku);exit;
                if ( ! empty($sku)) {
                    // 'goods_sku_id',
                    // 'exchange_type',
                    // 'exchange_coin',
                    // 'exchange_price sell_price', // 售价
                    // 'exchange_inventory goods_inventory', // 兑换库存
                    // 'cost_price', // 成本价
                    // 'sku_img',
                    // 'sku_title',
                    $goodsInfo['goodsSkuId']     = $sku['goods_sku_id'];
                    $goodsInfo['exchangeType']   = $sku['exchange_type'];
                    $goodsInfo['exchangeCoin']   = $sku['exchange_coin'];
                    $goodsInfo['sellPrice']      = $sku['sell_price'];
                    $goodsInfo['goodsInventory'] = $sku['goods_inventory'];
                    $goodsInfo['costPrice']      = $sku['cost_price'];
                    $goodsInfo['goodsImg']       =  ! empty($sku['sku_img']) ? $sku['sku_img'] : $goodsInfo['goodsImg'];
                }
            }
            $goodsInfo['skuTitle'] = $sku['sku_title'] ?? '';
            $goodsInfo['skuId']    = $sku['sku_id'] ?? 0;
            $goodsInfo['quantity'] = $v['quantity'];
            $goodsInfo['remark']   = $v['remark'] ?? '';
            $goodsInfo['sale']     = 0; // 优惠金额

            // 不包邮、关联运费模版ID为空，应当报错
            if ($goodsInfo['isPostage'] == 0 && $goodsInfo['spId'] == 0) {
                continue;
            }
            // 是否包邮  0否，1是  默认：1
            if ($goodsInfo['isPostage'] == 0) {
                $goodsInfo['postage'] = OrderService::getInstance()->getPostAge(
                    $goodsInfo['spId'],
                    $v['quantity'],
                    $goodsInfo['sellPrice']);
            } else {
                $goodsInfo['postage'] = 0;
            }

            $info[$goodsInfo['shopId']]['goodsInfo'][] = $goodsInfo;
        }
        foreach ($info as $shopId => &$item) {
            $shopInfo = ShopService::getInstance()->shopInfo($shopId);
            // shopType 1线下 2线上
            // orderType 1线下直付单 2线上单 3线下单 4供应链
            if ($shopInfo) {
                $shopInfo['orderType'] = ($shopInfo['shopType'] == 1) ? 3 : 2;
            }
            $item['shopInfo'] = empty($shopInfo) ? null : $shopInfo;
        }
        // var_dump($info);exit;
        return $info;
    }

    /**
     * 计算订单商品价格
     * @param  [type] $goodsInfo [description]
     * @param  [type] $uId       [description]
     * @param  array  $option    [description]
     * @return [type]            [description]
     */
    private function getOrderPrice($source, $exchange_type, $goodsInfo, $uId, $option = []): array
    {
        $getOrderNo = $option['getOrderNo'] ?? false;
        $orderNo    = $getOrderNo ? getNo('EX') : '';

        // orderType 1线下直付单 2线上单 3线下单 4供应链
        $orderType = $source == 2 ? 4 : 2;
        //总价
        $allSellPrice = 0;
        //总本金
        $allCostPrice = 0;
        //总邮费
        $allPostage = 0;
        //总优惠
        $allSale = 0;
        //总支付
        $allPayPrice = 0;
        // 总 积分
        $allCoin = 0;

        //每个店铺的总价
        $shopPriceList = [];
        //每个商品的总价
        $goodsPriceList = [];

        $skuList = [];

        foreach ($goodsInfo as $val) {
            $shopPrice    = 0; // 子订单总价
            $costPrice    = 0; // 子订单成本
            $shopPostage  = 0; // 子订单总邮费
            $shopSale     = 0; // 子订单优惠金额
            $shopQuantity = 0;
            $shopPayPrice = 0;
            $shopCoin     = 0; // 子订单积分
            $sub_order_no = $getOrderNo ? getNo('SB') : '';
            foreach ($val['goodsInfo'] as $goods) {
                $skuList[] = [
                    'goodsQty' => $goods['quantity'],
                    'skuId'    => $goods['skuId'],
                ];
                $sale = $goods['sale'] ?? 0; // 优惠金额

                // 'eg.exchange_inventory as goods_inventory',
                // 'eg.exchange_coin as exchange_coin',
                // 'eg.exchange_price',
                // 'eg.exchange_type',
                $payCoin  = bcmul($goods['exchangeCoin'], $goods['quantity'], 4);
                $shopCoin = bcadd($payCoin, $shopCoin, 4);

                $payPrice = bcmul($goods['sellPrice'], $goods['quantity'], 2); //商品总支付金额 = 价格x数量
                $payPrice = bcadd($goods['postage'], $payPrice, 2); //商品总支付金额 = 价格x数量+ 邮费

                $shopSale = bcsub($sale, $shopSale, 2); //商品总支付金额 = 价格x数量+ 邮费 - 优惠金额

                $shopPayPrice = bcadd($shopPayPrice, $payPrice, 2); //店铺总支付金额 = 原总金额+支付总金额
                $shopPayPrice = bcsub($shopPayPrice, $shopSale, 2); //店铺总支付金额 = 原总金额+支付总金额-优惠金额

                $shopPrice = bcadd(bcmul($goods['sellPrice'], $goods['quantity'], 2), $shopPrice, 2); //店铺商品总价 = 商品价格x数量+其他商品总价

                $costPrice    = bcadd(bcmul($goods['costPrice'], $goods['quantity'], 2), $costPrice, 2); //店铺商品成本总价 = 商品成本价格x数量+其他商品成本总价
                $shopPostage  = bcadd($goods['postage'], $shopPostage, 2); //店铺总邮费 = 商品总邮费+其他商品总邮费
                $shopQuantity = bcadd($goods['quantity'], $shopQuantity); //店铺卖出数量 = 商品数量+其他数量

                $goodsPriceList[] = [
                    'order_no'      => $orderNo,
                    'sub_order_no'  => $sub_order_no,
                    'exchange_type' => $exchange_type,
                    'pay_coin'      => $payCoin,
                    'quantity'      => $goods['quantity'],
                    'goods_id'      => $goods['id'],
                    'sku_id'        => $goods['skuId'],
                    'goods_sku_id'  => $goods['goodsSkuId'],
                    'goods_img'     => $goods['goodsImg'],
                    'goods_title'   => $goods['goodsTitle'],
                    'sku_title'     => $goods['skuTitle'],
                    'shop_id'       => $goods['shopId'],
                    'user_id'       => $uId,
                    'exchange_coin' => $goods['exchangeCoin'],
                    'sell_price'    => $goods['sellPrice'],
                    'cost_price'    => $goods['costPrice'],
                    'postage'       => $goods['postage'],
                    'pay_price'     => $payPrice,
                    'sale'          => $sale,
                    'remark'        => $goods['remark'],
                    'order_type'    => $goods['orderType'],
                    'gxz_rate'      => $goods['gxzRate'],
                ];
            }
            // var_dump($val['shopInfo']);exit;
            // orderType 1线下直付单 2线上单 3线下单 4供应链
            $orderType       = $val['shopInfo']['orderType'] ?? 4;
            $shopPriceList[] = [
                'user_id'       => $uId,
                'order_type'    => $source == 2 ? 4 : $orderType,
                'order_no'      => $orderNo,
                'sub_order_no'  => $sub_order_no,
                'exchange_type' => $exchange_type,
                'pay_price'     => $shopPayPrice,
                'shop_id'       => $val['shopInfo']['id'] ?? 0,
                'shop_name'     => $val['shopInfo']['shopName'] ?? 0,
                'sell_price'    => $shopPrice,
                'cost_price'    => $costPrice,
                'postage'       => $shopPostage,
                'quantity'      => $shopQuantity,
                'sale'          => $shopSale,
                'pay_coin'      => $shopCoin, // 子订单积分
            ];
            $allSellPrice = bcadd($allSellPrice, $shopPrice, 2);
            //总本金
            $allCostPrice = bcadd($costPrice, $allCostPrice, 2);
            //总邮费
            $allPostage = bcadd($shopPostage, $allPostage, 2);
            //总优惠
            $allSale = bcadd($shopSale, $allSale, 2);
            //总支付
            $allPayPrice = bcadd($shopPayPrice, $allPayPrice, 2);
            // 总积分
            $allCoin = bcadd($shopCoin, $allCoin, 4);
        }
        $allList = [
            'user_id'       => $uId,
            'order_type'    => $source == 2 ? 4 : $orderType,
            'order_no'      => $orderNo,
            'sell_price'    => $allSellPrice,
            'cost_price'    => $allCostPrice,
            'postage'       => $allPostage,
            'sale'          => $allSale,
            'expire_at'     => date('Y-m-d H:i:s', strtotime('+15 minutes')),
            'pay_price'     => $allPayPrice,
            'pay_amount'    => 0,
            'exchange_type' => $exchange_type,
            'pay_coin'      => $allCoin,
            'goods_list'    => json_encode($skuList, 320), // 供应链商品
        ];

        return [
            'shopPriceList'  => $shopPriceList,
            'allList'        => $allList,
            'goodsPriceList' => $goodsPriceList,
        ];
    }

    /**
     * @param $source 商品来源：1 日兮香商品 2 怡亚通商品
     * @param $goodsInfo
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function orderPreview($source, $exchange_type, $goodsItems): array
    {
        // [{"goodsId":1,"quantity":2,"skuId":1}]
        $goodsItems = json_decode($goodsItems, true);
        if (empty($goodsItems)) {
            CommonUtil::throwException(
                ErrorConst::PARAM_ERROR,
                ErrorConst::PARAM_ERROR_MSG);
        }
        //获取订单信息
        $goodsList = $this->getOrderGoodsInfo($source, $exchange_type, $goodsItems);
        // var_dump($goodsList);exit();
        if (empty($goodsList)) {
            CommonUtil::throwException(
                ErrorConst::PARAM_ERROR,
                ErrorConst::PARAM_ERROR_MSG);
        }
        $priceInfo = [];
        $priceInfo = $this->getOrderPrice(
            $source,
            $exchange_type,
            $goodsList,
            $this->userinfo->id);

        $finance = MemberService::getInstance()->finance($this->userinfo->id);

        $rows = empty($goodsList) ? [] : array_values($goodsList);
        foreach ($rows as &$v) {
            if (isset($v['goodsInfo']) && is_array($v['goodsInfo'])) {
                foreach ($v['goodsInfo'] as &$val) {
                    // exchangeCoin_4_to_2
                    $val['exchangeCoin'] = number_format($val['exchangeCoin'], 2, '.', '');
                }
            }
        }
        return [
            'rows'     => $rows,
            'finance'  => $finance,
            // 店铺总邮费 = 商品总邮费+其他商品总邮费
            'postage'  => $priceInfo['allList']['postage'] ?? '0.00',
            'sale'     => $priceInfo['allList']['sale'], // 总优惠
            // 'sellPrice' => $priceInfo['allList']['sell_price'],
            'payPrice' => $priceInfo['allList']['pay_price'],
            // exchangeCoin_4_to_2
            'payCoin'  => number_format($priceInfo['allList']['pay_coin'], 2, '.', ''),
        ];
    }

    /**
     * [createOrder description]
     * @param  [type]        $goodsInfo [description]
     * @param  [type]        $addressId [description]
     * @param  [type]        $orderType 1 线上（默认可以不传） 2线下
     * @param  float|integer $price     [description]
     * @param  float|integer $amount    [description]
     * @param  string        $userNotes [description]
     * @param  array         $option    [description]
     * @return [type]                   [description]
     */
    public function createOrder($goodsInfo, $addressId, $orderType, float $price = 0, float $amount = 0, $userNotes = '', $option = []): array
    {
        $coin          = $option['coin'] ?? -1;
        $source        = $option['source'] ?? 1;
        $exchange_type = $option['exchange_type'] ?? 0;
        // var_dump($option);exit;
        if ($price < 0 || $coin < 0 || empty($exchange_type)) {
            CommonUtil::throwException(
                ErrorConst::PARAM_ERROR,
                ErrorConst::PARAM_ERROR_MSG
            );
        }
        if ( ! RedLock::getInstance()->lock('createOrder:' . $this->userinfo->id, 1)) {
            CommonUtil::throwException(
                ErrorConst::FREQUENT_ERROR,
                ErrorConst::FREQUENT_ERROR_MSG
            );
        }
        $goodsInfo = json_decode($goodsInfo, true);
        // $goodsCart = $goodsInfo;
        if (empty($goodsInfo)) {
            CommonUtil::throwException(
                ErrorConst::PARAM_ERROR,
                ErrorConst::PARAM_ERROR_MSG
            );
        }

        $finance = MemberService::getInstance()->finance($this->userinfo->id);
        // var_dump($this->userinfo->id, $exchange_type, $coin, $finance['langlangScore'], $exchange_type == 1 && $coin > $finance['langlangScore']);exit;
        // 兑换类型 1 琅狼积分兑换 2 数字资产兑换 4 贡献值兑换
        if ( ! in_array($exchange_type, [1, 2, 4])) {
            CommonUtil::throwException(
                ErrorConst::PARAM_ERROR,
                ErrorConst::PARAM_ERROR_MSG
            );
        }
        if ($exchange_type == 1 && $coin > $finance['deduction']) {
            CommonUtil::throwException(
                ErrorConst::PRICE_ERROR,
                '抵扣券不足'
            );
        } elseif ($exchange_type == 2 && $coin > $finance['digitalMoney']) {
            CommonUtil::throwException(
                ErrorConst::PRICE_ERROR,
                '数字资产不足'
            );
        } elseif ($exchange_type == 4 && $coin > $finance['gxz']) {
            CommonUtil::throwException(
                ErrorConst::PRICE_ERROR,
                '贡献值不足'
            );
        }

        // 获取订单商品信息
        $goodsList = $this->getOrderGoodsInfo($source, $exchange_type, $goodsInfo);
        if (empty($goodsList)) {
            CommonUtil::throwException(
                ErrorConst::PARAM_ERROR,
                ErrorConst::PARAM_ERROR_MSG
            );
        }
        // 计算订单支付信息
        $priceInfo = $this->getOrderPrice(
            $source,
            $exchange_type,
            $goodsList,
            $this->userinfo->id,
            [
                'getOrderNo' => true,
            ]);
        // var_dump($priceInfo);exit;
        $price = bcadd($price, $amount, 2);
        if ($priceInfo['allList']['pay_price'] != $price) {
            CommonUtil::throwException(
                ErrorConst::PRICE_ERROR,
                ErrorConst::PRICE_ERROR_MSG
            );
        }
        // var_dump($priceInfo['allList']['pay_coin']);exit;
        if ($priceInfo['allList']['pay_coin'] != $coin) {
            CommonUtil::throwException(
                ErrorConst::PRICE_ERROR,
                ErrorConst::PRICE_ERROR_MSG
            );
        }
        if ($amount > 0) {
            if ($amount > $finance['amount']) {
                CommonUtil::throwException(
                    ErrorConst::NO_PRICE_ERROR,
                    ErrorConst::NO_PRICE_ERROR_MSG
                );
            }
            $priceInfo['allList']['pay_price']  = bcsub($priceInfo['allList']['pay_price'], $amount, 2);
            $priceInfo['allList']['pay_amount'] = $amount;
        }
        $addressInfo = MemberService::getInstance()->addressDetail(
            $this->userinfo->id,
            $addressId, 2);
        if (empty($addressInfo) && $orderType == 1) {
            CommonUtil::throwException(
                ErrorConst::NO_ADDRESS_ERROR,
                ErrorConst::NO_ADDRESS_ERROR_MSG
            );
        }
        $priceInfo['allList']['user_note'] = $userNotes;

        $orderNo = $this->doCreateOrder($exchange_type, $finance, $priceInfo, $addressInfo);
        // var_dump($orderNo);exit;
        if (empty($orderNo)) {
            CommonUtil::throwException(
                ErrorConst::SYSTEM_ERROR,
                ErrorConst::SYSTEM_ERROR_MSG
            );
        }
        $isBalance = 0;
        if ($priceInfo['allList']['pay_price'] == 0) {
            $isBalance = 1;

            $info = $this->payCoin(
                $orderNo,
                $exchange_type,
                $priceInfo['allList']['pay_coin'],
                $finance,
                [
                    'source' => $source,
                ]
            );
            if ( ! $info) {
                CommonUtil::throwException(
                    ErrorConst::SYSTEM_ERROR,
                    ErrorConst::SYSTEM_ERROR_MSG
                );
            }
        }

        //$goodsCart
        // CartService::getInstance()->delCart($goodsCart, $this->userinfo->id);

        return [
            'isBalance' => $isBalance,
            'orderNo'   => $orderNo,
            'expireAt'  => $priceInfo['allList']['expire_at']];
    }

    /**
     * [changeCoin description]
     * @param  [type] $log_type   exchange_pay 积分兑换消费; exchange_refund 积分兑换取消订单
     * @param  [type] $logTable   [description]
     * @param  [type] $field      [description]
     * @param  [type] $act      自增/自减  inc/dec
     * @param  [type] $coin       [description]
     * @param  [type] $thisAmount [description]
     * @param  [type] $userId     [description]
     * @return [type]             [description]
     */
    private function changeCoin($log_type, $logTable, $field, $act, $coin, $thisAmount, $userId, $msg, $orderNo)
    {
        $alterAmount = $act == 'dec' ? bcsub($thisAmount, $coin, 4) : bcadd($thisAmount, $coin, 4);
        $data        = [
            'user_id'      => $userId,
            // 1加 2减少
            'status'       => $act == 'dec' ? 2 : 1,
            'log_type'     => $log_type,
            'remark'       => $msg . '，当前贡献值' . $alterAmount,
            'this_amount'  => $thisAmount,
            'alter_amount' => $alterAmount,
            'amount'       => $coin,
            'order_no'     => $orderNo,
        ];
        $res1 = \think\facade\Db::table($logTable)->insert($data);
        if ($act == 'dec') {
            $res2 = \think\facade\Db::table('member_finance')
                ->where(['user_id' => $userId])
                ->dec($field, $coin)
                ->update();
        } else {
            $res2 = \think\facade\Db::table('member_finance')
                ->where(['user_id' => $userId])
                ->inc($field, $coin)
                ->update();
        }
        return $res1 && $res2;
    }

    private function payCoin($orderNo, $exchange_type, $coin, $finance, $option = [])
    {
        // 商品来源：1 日兮香商品 2 怡亚通商品
        $source = $option['source'] ?? 0;

        $pay_at = date('Y-m-d H:i:s');
        \think\facade\Db::startTrans();
        try {
            // 兑换类型 1 抵扣券兑换 2 数字资产兑换 4 贡献值兑换
            if ($exchange_type == 1) {
                $msg = '抵扣券兑换商品，订单号' . $orderNo;
                /*$this->changeCoin(
                    'exchange_pay',
                    'member_langlang_score_log',
                    'langlang_score',
                    'dec',
                    $coin,
                    $finance['langlangScore'],
                    $finance['userId'],
                    $msg,
                    $orderNo,
                );*/
                MemberService::getInstance()->addFinanceLog($finance['userId'], 'change', $coin, 8, $msg, $orderNo);
            } elseif ($exchange_type == 2) {
                $msg = '数字资产兑换商品，订单号' . $orderNo;
                $this->changeCoin(
                    'exchange_pay',
                    'member_digital_money_log',
                    'digital_money',
                    'dec',
                    $coin,
                    $finance['digitalMoney'],
                    $finance['userId'],
                    $msg,
                    $orderNo,
                );
            } elseif ($exchange_type == 4) {
                $msg = '贡献值兑换商品，订单号' . $orderNo;
                $this->changeCoin(
                    'exchange_pay',
                    'member_gxz_log',
                    'gxz',
                    'dec',
                    $coin,
                    $finance['gxz'],
                    $finance['userId'],
                    $msg,
                    $orderNo,
                );
            }

            \think\facade\Db::table('exchange_order')
                ->where('order_no', $orderNo)
                ->update([
                    'status'    => 1, // 待发货
                    'pay_at'    => $pay_at,
                    'update_at' => $pay_at,
                ]);
            \think\facade\Db::table('exchange_order_sub')
                ->where('order_no', $orderNo)
                ->update([
                    'status'    => 1, // 待发货
                    'pay_at'    => $pay_at,
                    'update_at' => $pay_at,
                ]);
            \think\facade\Db::table('exchange_order_goods')
                ->where('order_no', $orderNo)
                ->update([
                    'status'    => 1, // 待发货
                    'update_at' => $pay_at,
                ]);
            // 供应商推单
            // source 商品来源： 1 日兮香商品 2 怡亚通商品
            if ($source == 2) {
                $orderAddress = \think\facade\Db::table('exchange_order_address')
                    ->field(['real_name', 'phone', 'address'])
                    ->where('order_no', $orderNo)
                    ->find();
                $od = \think\facade\Db::table('exchange_order')
                    ->field(['goods_list', 'addr_path'])
                    ->where('order_no', $orderNo)
                    ->find();
                $ret = \app\api\services\SupplyService::getInstance()->submitOrder(
                    $od['goods_list'],
                    $orderAddress['real_name'],
                    $orderAddress['address'],
                    $orderAddress['phone'],
                    $od['addr_path'],
                    $orderNo);
                \think\facade\Log::info('供应链下单返回参数:' . json_encode($ret, 320));
                if (empty($ret) || $ret['status'] != 200) {
                    \think\facade\Db::rollback();
                    return false;
                }
            }
            // end 供应商推单
        } catch (\Exception $e) {
            \think\facade\Db::rollback();
            $msg = json_encode(['message' => $e->getMessage(), 'trace' => $e->getTrace()], 320);
            \think\facade\Log::error('[ExchangeOrder/payCoin] 出错' . $msg);
            return false;
        }
        \think\facade\Db::commit();

        return true;
    }

    /**
     *  获取 供应链省市区编码
     * @param  [type] $addressInfo [description]
     * @return [type]              [description]
     */
    private function getAddrPath($address)
    {
        // var_dump($address['province']);exit;
        // var_dump($address);exit;
        $cityCode = '';
        if ($address) {
            $provinceRegion = SupplyService::getInstance()->getRegionByCodeOpen();
            // var_dump($provinceRegion);exit;
            $keyName  = '';
            $province = mb_substr($address['province'], 0, 2);
            foreach ($provinceRegion['data'] as $vv) {
                if (mb_substr($vv['name'], 0, 2) == $province) {
                    $keyName = $vv['regionCode'];
                    break;
                }
            }
            if ( ! empty($keyName)) {
                $cityRegion = SupplyService::getInstance()->getRegionByCodeOpen($keyName);
                foreach ($cityRegion['data'] as $vvv) {
                    if (mb_substr($vvv['name'], 0, 2) == $province) {
                        $cityCode = $vvv['regionCode'];
                        break;
                    }
                }
                if ( ! $cityCode) {
                    $cityData = array_column($cityRegion['data'], 'name', 'regionCode');
                    $cityCode = array_search($address['city'], $cityData);
                }
            }
        }

        $areaRegion = SupplyService::getInstance()->getRegionByCodeOpen($cityCode);
        $areaData   = array_column($areaRegion['data'], 'name', 'regionFullCodes');
        if ($address['city'] == $address['country']) {
            $address['country'] = $address['street'];
        }
        $keyName = array_search($address['country'], $areaData);
        if ( ! $keyName) {
            CommonUtil::throwException(ErrorConst::NO_ADDRESS_ERROR, ErrorConst::NO_ADDRESS_ERROR_MSG);
        }
        $arr      = explode(',', $keyName);
        $newArr   = array_reverse($arr);
        $addrPath = implode(',', $newArr);
        return $addrPath;
    }

    private function doCreateOrder($exchange_type, $finance, $priceInfo, $addressInfo)
    {
        // 供应链省市区编码
        $priceInfo['allList']['addr_path'] = $this->getAddrPath($addressInfo);
        // var_dump($priceInfo['allList']['addr_path']);exit;
        // $order = \app\common\models\ExchangeOrder::getInstance();
        \think\facade\Db::startTrans();
        try {
            $orderId = \think\facade\Db::table('exchange_order')
                ->insertGetId($priceInfo['allList']);
            if ( ! $orderId) {
                \think\facade\Db::rollback();
                return false;
            }
            if ( ! empty($addressInfo)) {
                $addressInfo['order_no'] = $priceInfo['allList']['order_no'];

                $address = \think\facade\Db::table('exchange_order_address')
                    ->insert($addressInfo);
                if ( ! $address) {
                    \think\facade\Db::rollback();
                    return false;
                }
            }

            $subOrder = \think\facade\Db::table('exchange_order_sub')
                ->insertAll($priceInfo['shopPriceList']);
            if ( ! $subOrder) {
                \think\facade\Db::rollback();
                return false;
            }

            $order = \think\facade\Db::table('exchange_order_goods')
                ->insertAll($priceInfo['goodsPriceList']);
            if ( ! $order) {
                \think\facade\Db::rollback();
                return false;
            }
            foreach ($priceInfo['goodsPriceList'] as $item) {
                $goods_id     = $item['goods_id'];
                $goods_sku_id = $item['goods_sku_id'];
                \think\facade\Db::table('exchange_goods')
                    ->where('goods_id', $goods_id)
                    ->inc('exchange_count', $item['quantity'])
                    ->dec('exchange_inventory', $item['quantity'])
                    ->update();
                if ($goods_sku_id > 0) {
                    \think\facade\Db::table('exchange_goods_sku')
                        ->where('goods_id', $goods_id)
                        ->where('goods_sku_id', $goods_sku_id)
                        ->inc('exchange_count', $item['quantity'])
                        ->dec('exchange_inventory', $item['quantity'])
                        ->update();
                }
            }
        } catch (\Exception $e) {
            \think\facade\Db::rollback();
            $msg = json_encode(['message' => $e->getMessage(), 'trace' => $e->getTrace()], 320);
            \think\facade\Log::error('[ExchangeOrder/doCreateOrder] 出错' . $msg);
            return false;
        }
        \think\facade\Db::commit();
        return $priceInfo['allList']['order_no'];
    }

    /**
     * 确认收货
     * @param  [type] $orderNo [description]
     * @return [type]          [description]
     */
    public function taskOrder($orderNo): bool
    {
        if ( ! RedLock::getInstance()->lock('taskOrder_' . $this->userinfo->id, 1)) {
            CommonUtil::throwException(
                ErrorConst::FREQUENT_ERROR,
                ErrorConst::FREQUENT_ERROR_MSG);
        }
        //0待支付 1待发货 2待收款 3已收货 4已完成 5退款中 6退款成功 7取消 8超时取消 9待退货
        $order = $this->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($order)) {
            CommonUtil::throwException(
                ErrorConst::PARAM_ERROR,
                ErrorConst::PARAM_ERROR_MSG);
        }
        if ($order['status'] == 3 || $order['status'] == 4) {
            return true;
        }
        if ($order['status'] != 2) {
            CommonUtil::throwException(
                ErrorConst::ORDER_STATUS_ERROR,
                ErrorConst::ORDER_STATUS_ERROR_MSG);
        }
        $where = [
            'order_no' => $orderNo,
            'status'   => 2,
        ];

        $goodsOrder = ExchangeOrderGoods::getInstance()->where($where)->select();
        if (empty($goodsOrder)) {
            return false;
        }

        ExchangeOrder::getInstance()->startTrans();
        try {
            $update = [
                'status'  => 3,
                'task_at' => date('Y-m-d H:i:s'),
            ];
            //修改主单状态
            ExchangeOrder::getInstance()->where($where)->update($update);
            ExchangeOrderGoods::getInstance()->where($where)->update($update);
            ExchangeOrderSub::getInstance()->where($where)->update($update);
            // 积分兑换订单，不需要分润、直推人奖励或者给商家打款等？ TODO 2024-06-15
            /*
            foreach ($goodsOrder as $val) {
                if ($val['shopId']) {
                    //获取商户信息
                    $shopInfo = ShopService::getInstance()->getShopInfoById(
                        $val['shopId'],
                        'id,shop_name,user_id,status,score_rate,gxz_rate,platform_fee');
                    //给商户钱
                    $goodsAllAmount = bcadd($val['payPrice'], $val['sale'], 2);
                    $msg            = '商品' . $val['goodsTitle'] . '出售成功，获得' . $goodsAllAmount;
                    //加商户总金额
                    MemberService::getInstance()->addFinanceLog(
                        $shopInfo['userId'],
                        'order_task',
                        $goodsAllAmount,
                        2,

                        $msg);
                    $gxzRate = $val['gxzRate'] > 0 ? $val['gxzRate'] : $shopInfo['gxzRate'];
                    if ($gxzRate > 0) {
                        $money = bcmul($goodsAllAmount, $gxzRate * 0.01, 4);
                        if ($money > 0) {
                            $msg = '线上订单消费，赠送贡献值，订单号' . $orderNo;
                            MemberService::getInstance()->addFinanceLog($val['userId'], 'online', $money, 7, $msg, $val['orderNo']);
                        }
                    }
                    //分润池
                    //1线下直付单 2线上单 3线下单 4供应链
                    //1线上订单 2线下订单 3怡亚通订单 4社区订单 5礼包订单
                    $profit = 0;
                    if (in_array($val['orderType'], [1, 3])) {
                        $type = 2;
                    } elseif ($val['orderType'] == 2) {
                        $profit = bcmul($val['sellPrice'], bcmul($shopInfo['platformFee'], 0.01, 4), 4);
                        $type   = 1;
                    } else {
                        //供应链
                        $profit = bcsub($val['sellPrice'], $shopInfo['costPrice'], 4);
                        $type   = 3;
                    }
                    MemberService::getInstance()->profitPoolLog($val['userId'], $val['sellPrice'], $orderNo, $profit, $type);
                }
                //供应链
                if ($val['orderType'] == 4) {
                    if ($val['gxzRate'] > 0) {
                        $money = bcmul($val['payPrice'], $val['gxzRate'] * 0.01, 4);
                        if ($money > 0) {
                            $msg = '供应连订单消费，赠送贡献值，订单号' . $orderNo;
                            MemberService::getInstance()->addFinanceLog(
                                $val['userId'],
                                'online',
                                $money,
                                7,
                                $msg,
                                $val['orderNo']);
                        }
                    }
                }
                // $this->dividend($val);
            }
            */
        } catch (\Exception $e) {
            Log::error($e->getMessage());
            ExchangeOrder::getInstance()->rollback();
            return false;
        }
        ExchangeOrder::getInstance()->commit();
        return true;
    }
}
